﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using HigLabo.Net.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;

namespace HigLabo.Net.Facebook
{
    /// <summary>
    /// 
    /// </summary>
    public partial class FacebookClient
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<User> GetUserAsync()
        {
            return this.GetUserAsync("me");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<User> GetUserAsync(String id)
        {
            return this.GetUserAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<User> GetUserAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, User>(this.GetUser, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Page> GetPageAsync(String id)
        {
            return GetPageAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<Page> GetPageAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, Page>(this.GetPage, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<PostData> GetHomeAsync()
        {
            return this.GetHomeAsync("me");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<PostData> GetHomeAsync(String id)
        {
            return this.GetHomeAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<PostData> GetHomeAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, PostData>(this.GetHome, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<PostData> GetFeedAsyc()
        {
            return this.GetFeedAsyc("me");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<PostData> GetFeedAsyc(String id)
        {
            return this.GetFeedAsyc(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<PostData> GetFeedAsyc(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, PostData>(this.GetFeed, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<PostData> GetStatusesAsync()
        {
            return this.GetStatusesAsync("me");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<PostData> GetStatusesAsync(String id)
        {
            return this.GetStatusesAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<PostData> GetStatusesAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, PostData>(this.GetStatuses, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<PostData> GetPostDataAsync(PostData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<PostData>(data, mode, this.GetPostData);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<LikeData> GetLikesAsync(String id)
        {
            return this.GetLikesAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<LikeData> GetLikesAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, LikeData>(this.GetLikes, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<LikeData> GetLikesAsync(LikeData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<LikeData>(data, mode, this.GetLikes);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Comment> GetCommentAsync(String id)
        {
            return AsyncCall<String, Comment>(this.GetComment, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<Comment> GetCommentAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, Comment>(this.GetComment, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<CommentData> GetCommentsAsync(String id)
        {
            return AsyncCall<String, CommentData>(this.GetComments, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<CommentData> GetCommentsAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, CommentData>(this.GetComments, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<CommentData> GetCommentsAsync(CommentData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<CommentData>(data, mode, this.GetComments);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Book> GetBookAsync(String id)
        {
            return AsyncCall<String, Book>(this.GetBook, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<Book> GetBookAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, Book>(this.GetBook, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<BookData> GetBooksAsync(String id)
        {
            return AsyncCall<String, BookData>(this.GetBooks, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<BookData> GetBooksAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, BookData>(this.GetBooks, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<MusicData> GetMusicAsync(String id)
        {
            return AsyncCall<String, MusicData>(this.GetMusicList, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<MusicData> GetMusicAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, MusicData>(this.GetMusicList, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<MusicData> GetMusicListAsync(String id)
        {
            return AsyncCall<String, MusicData>(this.GetMusicList, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<MusicData> GetMusicListAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, MusicData>(this.GetMusicList, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Movie> GetMovieAsync(String id)
        {
            return AsyncCall<String, Movie>(this.GetMovie, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<MovieData> GetMoviesAsync(String id)
        {
            return AsyncCall<String, MovieData>(this.GetMovies, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<MovieData> GetMoviesAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, MovieData>(this.GetMovies, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Television> GetTelevisionAsync(String id)
        {
            return AsyncCall<String, Television>(this.GetTelevision, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<TelevisionData> GetTelevisionsAsync(String id)
        {
            return this.GetTelevisionsAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<TelevisionData> GetTelevisionsAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, TelevisionData>(this.GetTelevisions, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<TelevisionData> GetTelevisionsAsync(TelevisionData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<TelevisionData>(data, mode, this.GetTelevisions);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<User> GetFriendAsync(String id)
        {
            return AsyncCall<String, User>(this.GetFriend, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<FriendData> GetFriendsAsync()
        {
            return this.GetFriendsAsync("me");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<FriendData> GetFriendsAsync(String id)
        {
            return this.GetFriendsAsync(new GetObjectCommand(id));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<FriendData> GetFriendsAsync(GetObjectCommand command)
        {
            return AsyncCall<GetObjectCommand, FriendData>(this.GetFriends, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<FriendData> GetFriendsAsync(FriendData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<FriendData>(data, mode, this.GetFriends);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<NotificationData> GetNotificationsAsync()
        {
            return AsyncCall<NotificationData>(this.GetNotifications);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<NotificationData> GetNotificationsAsync(NotificationData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<NotificationData>(data, mode, this.GetNotifications);
        }
        public Task<TResult> GetPagingDataAsync<TResult>(GraphApiResponseData data, PagingMode mode, Action<HttpRequestCommand, Action<TResult>> action)
            where TResult: new()
        {
            var url = data.Paging.GetUrl(mode);
            if (String.IsNullOrEmpty(url) == true)
            {
                var result = new TaskCompletionSource<TResult>();
                result.SetResult(new TResult());
                return result.Task;
            }
            var command = this.CreateCommand(HttpMethodName.Get, url);
            return AsyncCall<HttpRequestCommand, TResult>(action, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<InboxData> GetInboxAsync()
        {
            return AsyncCall<InboxData>(this.GetInbox);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<InboxData> GetInboxAsync(InboxData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<InboxData>(data, mode, this.GetInbox);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Task<OutboxData> GetOutboxAsync()
        {
            return AsyncCall<OutboxData>(this.GetOutbox);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public Task<OutboxData> GetOutboxAsync(OutboxData data, PagingMode mode)
        {
            return this.GetPagingDataAsync<OutboxData>(data, mode, this.GetOutbox);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Boolean> LikeAsync(String id)
        {
            return AsyncCall<String, Boolean>(this.Like, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Boolean> UnLikeAsync(String id)
        {
            return AsyncCall<String, Boolean>(this.UnLike, id);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<String> AddCommentAsync(AddCommentCommand command)
        {
            return AsyncCall<AddCommentCommand, String>(this.AddComment, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public Task<String> AddStatusAsync(AddStatusCommand command)
        {
            return AsyncCall<AddStatusCommand, String>(this.AddStatus, command);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Task<Boolean> DeleteObjectAsync(String id)
        {
            return this.DeleteObjectAsync(new FacebookCommand(id));
        }
        public Task<Boolean> DeleteObjectAsync(FacebookCommand command)
        {
            return AsyncCall<FacebookCommand, Boolean>(this.DeleteObject, command);
        }
    }
}
